package com.markby.fscm.cryptogram.domain.standard0018;


import com.markby.fscm.cryptogram.uitls.HexUtils;
import lombok.Getter;

import java.nio.ByteOrder;


import static com.markby.fscm.cryptogram.domain.standard0016.Constant0016.ECC_MAX_XCOORDINATE_BITS_LEN;
import static com.markby.fscm.cryptogram.domain.standard0018.Constant0018.ECCref_MAX_LEN;
import static com.markby.fscm.cryptogram.uitls.HexUtils.intToBytes;


/**
 * 0018-2023规范 ECC加密数据结构
 * ULONG 为32位无符号整数
 * typedef struct ECCCipher_st
 * {
 * 	BYTE x[ECCref_MAX_LEN];		// X分量（ECCref_MAX_LEN字节）
 * 	BYTE y[ECCref_MAX_LEN];		// Y分量（ECCref_MAX_LEN字节）
 * 	BYTE M[32];					// 明文的杂凑值（32字节）
 * 	ULONG L;					// 密文数据长度(4字节)
 * 	BYTE C[];					// 密文数据(L字节)
 * }ECCCipher;
 */
public class ECCCipher {

    private byte[] x;
    private byte[] y;
    private byte[] M;
    @Getter
    private int L;
    private byte[] C;

    public ECCCipher(byte[] x, byte[] y, byte[] m, int l, byte[] c) {
        if (x.length != ECCref_MAX_LEN) {
            throw new IllegalArgumentException("Invalid x length: " + x.length);
        }
        if (y.length != ECCref_MAX_LEN) {
            throw new IllegalArgumentException("Invalid y length: " + y.length);
        }
        if (m.length != 32) {
            throw new IllegalArgumentException("Invalid M length: " + m.length);
        }
        if (c.length != l) {
            throw new IllegalArgumentException("Invalid C length: " + c.length);
        }
        this.x = x;
        this.y = y;
        this.M = m;
        this.L = l;
        this.C = c;
    }

    public ECCCipher(byte[] randomNumEncryptWithSM2, int ulBits) {
        if (randomNumEncryptWithSM2.length != 113) {
            throw new IllegalArgumentException("ECCCIPHERBLOB length must be 113");
        }
        System.out.println("对称密钥密文长度:" + randomNumEncryptWithSM2.length);
        System.out.println("对称密钥密文:" + HexUtils.hexify_haveSpace(randomNumEncryptWithSM2));
        if (ulBits == 256) {
            int len = ECC_MAX_XCOORDINATE_BITS_LEN / 8 / 2;
            byte[] x = new byte[32];//x分量
            byte[] y = new byte[32];//y分量
            byte[] m = new byte[32];//杂凑值
            byte[] c = new byte[16];//密文
            System.arraycopy(randomNumEncryptWithSM2, 1, x, 0, len);
            System.arraycopy(randomNumEncryptWithSM2, 33, y, 0, len);
            System.arraycopy(randomNumEncryptWithSM2, 65, m, 0, 32);
            System.arraycopy(randomNumEncryptWithSM2, 97, c, 0, 16);

            this.x = new byte[64];
            this.y = new byte[64];
            System.arraycopy(x, 0, x, x.length - len, len);
            System.arraycopy(y, 0, y, y.length - len, len);
            this.M = m;
            this.L = c.length;
            this.C = c;
        } else {
            throw new IllegalArgumentException("ECCCIPHERBLOB NOT SUPPORT BitLen 512 FOR NOW!");
        }
    }

    public byte[] getBytes() {
        byte[] xBytes = x;
        byte[] yBytes = y;
        byte[] MBytes = M;
        byte[] LBytes = intToBytes(L, ByteOrder.LITTLE_ENDIAN);
        byte[] CBytes = C;
        byte[] result = new byte[xBytes.length + yBytes.length + MBytes.length + LBytes.length + CBytes.length];
        System.arraycopy(xBytes, 0, result, 0, xBytes.length);
        System.arraycopy(yBytes, 0, result, xBytes.length, yBytes.length);
        System.arraycopy(MBytes, 0, result, xBytes.length + yBytes.length, MBytes.length);
        System.arraycopy(LBytes, 0, result, xBytes.length + yBytes.length + MBytes.length, LBytes.length);
        System.arraycopy(CBytes, 0, result, xBytes.length + yBytes.length + MBytes.length + LBytes.length, CBytes.length);
        return result;
    }

}
